package net.lijingye.education.dao.impl;

import net.lijingye.education.dao.BaseDao;
import net.lijingye.education.exception.DaoException;
import org.hibernate.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * Created by LijingYe on 2016/3/29.
 */
public abstract class BaseDaoImpl<T extends Serializable> implements BaseDao<T> {
    @Autowired
    protected SessionFactory sessionFactory;

    private Class<T> entityClass;

    public BaseDaoImpl() {
        Type genType = getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        entityClass = (Class) params[0];
    }

    public T getById(Serializable id) throws DaoException {
        try {
            Session session = sessionFactory.getCurrentSession();
            return (T) session.get(entityClass, id);
        } catch (ObjectNotFoundException e) {
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            throw new DaoException(e.getMessage());
        }
    }

    public T getByQuery(String queryString) throws DaoException {
        try {
            String hql = "from " + entityClass.getName() + " " + queryString;
            Session session = sessionFactory.getCurrentSession();
            Query query = session.createQuery(hql);
            List resultList = query.list();
            if (1 == resultList.size()) {
                return (T) resultList.get(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new DaoException(e.getMessage());
        }
        return null;
    }

    public void save(T entity) throws DaoException {
        try {
            Session session = sessionFactory.getCurrentSession();
            session.save(entity);
        } catch (Exception e) {
            e.printStackTrace();
            throw new DaoException(e.getMessage());
        }
    }

    public void update(T entity) throws DaoException {
        try {
            Session session = sessionFactory.getCurrentSession();
            session.update(entity);
        } catch (Exception e) {
            e.printStackTrace();
            throw new DaoException(e.getMessage());
        }
    }

    public void saveOrUpdate(T entity) throws DaoException {
        try {
            Session session = sessionFactory.getCurrentSession();
            session.saveOrUpdate(entity);
        } catch (Exception e) {
            e.printStackTrace();
            throw new DaoException(e.getMessage());
        }
    }

    public void delete(T entity) throws DaoException {
        try {
            Session session = sessionFactory.getCurrentSession();
            session.delete(entity);
        } catch (Exception e) {
            e.printStackTrace();
            throw new DaoException(e.getMessage());
        }
    }

    public List<T> findByQuery(String queryString) throws DaoException {
        try {
            String hql = "from " + entityClass.getName() + " " + queryString;
            Session session = sessionFactory.getCurrentSession();
            Query query = session.createQuery(hql);
            return (List<T>) query.list();
        } catch (Exception e) {
            e.printStackTrace();
            throw new DaoException(e.getMessage());
        }
    }

    public List<T> findAll() throws DaoException {
        Session session = sessionFactory.getCurrentSession();
        Criteria criteria = session.createCriteria(entityClass);
        return (List<T>) criteria.list();
    }
}
